package com.cek.tdrive.home;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.cek.tdrive.R;
import com.cek.tdrive.settings.Settings;
import com.cek.tdrive.travel.AlertActivity;
import com.cek.tdrive.travel.CostActivity;
import com.cek.tdrive.travel.VehicleActivity;
import com.cek.tdrive.travel.WeatherActivity;

import com.cek.view.MyHorizontalScrollView;
import com.cek.view.MyHorizontalScrollView.SizeCallback;
import com.cek.view.ViewUtils;
import com.cek.tdrive.adapter.MenuAdapter;
import com.cek.tdrive.base.TDriveBaseActivity;
import com.cek.tdrive.comon.HttpASync;
import com.cek.tdrive.comon.HttpASync.OnRequest;
import com.cek.tdrive.constant.AppConstant;
import com.cek.tdrive.data.TDistance;
import com.cek.tdrive.data.TRoute;
import com.cek.tdrive.data.Vehicle;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class HomeScreenActivity extends TDriveBaseActivity implements
		OnItemClickListener, OnRequest, OnMapClickListener {
	private MyHorizontalScrollView scrollView;
	private View menu;
	private View app;
	private ImageView btnSlide;

	private ClickListenerForScrolling clickListener;

	private MenuAdapter menuAdapter;
	private static final int SWIPE_MIN_DISTANCE = 120;
	private static final int SWIPE_MAX_OFF_PATH = 250;
	private static final int SWIPE_THRESHOLD_VELOCITY = 200;
	private GestureDetector gestureDetector;
	View.OnTouchListener gestureListener;
	private GoogleMap googleMap;
	private List<Polyline> line = new ArrayList<Polyline>();
	private static final int ROUTE_ACTIVITY = 25;
	private int firstRoute = 0;
	private LatLng currentlocation;
	private List<TRoute> routesOptions;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		LayoutInflater inflater = LayoutInflater.from(this);
		scrollView = (MyHorizontalScrollView) inflater.inflate(
				R.layout.horz_scroll_with_list_menu, null);
		setContentView(scrollView);

		menu = inflater.inflate(R.layout.horz_scroll_menu, null);
		app = inflater.inflate(R.layout.horz_scroll_app, null);
		ViewGroup tabBar = (ViewGroup) app.findViewById(R.id.tabBar);

		ListView listView_list = (ListView) menu.findViewById(R.id.list);
		menuAdapter = new MenuAdapter(this);
		listView_list.setAdapter(menuAdapter);
		listView_list.setOnItemClickListener(this);

		btnSlide = (ImageView) tabBar.findViewById(R.id.BtnSlide);
		clickListener = new ClickListenerForScrolling(scrollView, menu);
		btnSlide.setOnClickListener(clickListener);

		final View[] children = new View[] { menu, app };

		// Scroll to app (view[1]) when layout finished.
		int scrollToViewIdx = 1;
		scrollView.initViews(children, scrollToViewIdx,
				new SizeCallbackForMenu(btnSlide));
		gestureDetector = new GestureDetector(this, new MyGestureDetector());
		gestureListener = new View.OnTouchListener() {
			public boolean onTouch(View v, MotionEvent event) {
				return gestureDetector.onTouchEvent(event);
			}
		};
		scrollView.setOnTouchListener(gestureListener);
	}

	/**
	 * Helper for examples with a HSV that should be scrolled by a menu View's
	 * width.
	 */
	static class ClickListenerForScrolling implements OnClickListener {
		HorizontalScrollView scrollView;
		View menu;
		/**
		 * Menu must NOT be out/shown to start with.
		 */
		boolean menuOut = false;

		public ClickListenerForScrolling(HorizontalScrollView scrollView,
				View menu) {
			super();
			this.scrollView = scrollView;
			this.menu = menu;
		}

		@Override
		public void onClick(View v) {

			int menuWidth = menu.getMeasuredWidth();

			// Ensure menu is visible
			menu.setVisibility(View.VISIBLE);

			if (!menuOut) {
				// Scroll to 0 to reveal menu
				int left = 0;
				scrollView.smoothScrollTo(left, 0);
			} else {
				// Scroll to menuWidth so menu isn't on screen.
				int left = menuWidth;
				scrollView.smoothScrollTo(left, 0);
			}
			menuOut = !menuOut;
		}
	}

	/**
	 * Helper that remembers the width of the 'slide' button, so that the
	 * 'slide' button remains in view, even when the menu is showing.
	 */
	static class SizeCallbackForMenu implements SizeCallback {
		int btnWidth;
		View btnSlide;

		public SizeCallbackForMenu(View btnSlide) {
			super();
			this.btnSlide = btnSlide;
		}

		@Override
		public void onGlobalLayout() {
			btnWidth = btnSlide.getMeasuredWidth();
			System.out.println("btnWidth=" + btnWidth);
		}

		@Override
		public void getViewSize(int idx, int w, int h, int[] dims) {
			dims[0] = w;
			dims[1] = h;
			final int menuIdx = 0;
			if (idx == menuIdx) {
				dims[0] = w - btnWidth;
			}
		}
	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View v, int position, long id) {
		if (position == AppConstant.EXIT) {
			finish();// TODO Auto-generated method stub
		} else if (position == AppConstant.MY_VEHICLES) {
			Intent intent = new Intent(this, VehicleActivity.class);
			startActivity(intent);
		} else if (position == AppConstant.ALERTS) {
			Intent intent = new Intent(this, AlertActivity.class);
			startActivity(intent);
		} else if (position == AppConstant.SETTINGS) {
			Intent intent = new Intent(this, Settings.class);
			startActivity(intent);
		} else if (position == AppConstant.TRAVEL_COST) {
			if (routesOptions != null) {
				long dur = routesOptions.get(0).getDesTdriveDuration();
				int index = 0;
				for (int i = 1; i < routesOptions.size(); i++) {
					if (routesOptions.get(i).getDesTdriveDuration() < dur) {
						dur = routesOptions.get(i).getDesTdriveDuration();
						index = i;
					}
				}

				Intent intent = new Intent(this, CostActivity.class);
				ArrayList<TDistance> steps = routesOptions.get(index)
						.getSteps();
				long dis = 0;
				for (TDistance tDistance : steps) {
					dis += tDistance.getDistance();
				}
				intent.putExtra("DISTANCE", dis);
				startActivity(intent);
			} else {
				Toast.makeText(getApplicationContext(),
						"Find a route to compute cost", Toast.LENGTH_SHORT)
						.show();
			}
		} else if (position == AppConstant.WEATHER) {
			Intent intent = new Intent(this, WeatherActivity.class);
			startActivity(intent);
		} else if (position == AppConstant.ROUTE) {
			Intent intent = new Intent(this, RouteActivity.class);
			startActivityForResult(intent, ROUTE_ACTIVITY);
		}

	}

	class MyGestureDetector extends SimpleOnGestureListener {
		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			try {
				if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
					return false;
				// right to left swipe
				if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
						&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
					clickListener.onClick(scrollView);
					// Toast.makeText(HomeScreen.this, "Left Swipe",
					// Toast.LENGTH_SHORT).show();
				} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
						&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
					clickListener.onClick(scrollView);
					;
					// Toast.makeText(HomeScreen.this, "Right Swipe",
					// Toast.LENGTH_SHORT).show();
				}
			} catch (Exception e) {
				// nothing
			}
			return false;
		}

		@Override
		public boolean onDown(MotionEvent e) {
			return true;
		}
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		initilizeMap();

	}

	private void initilizeMap() {
		if (googleMap == null) {
			FragmentManager fmanager = getSupportFragmentManager();
			Fragment fragment = fmanager.findFragmentById(R.id.mapview);
			SupportMapFragment supportmapfragment = (SupportMapFragment) fragment;
			googleMap = supportmapfragment.getMap();
			// check if map is created successfully or not
			if (googleMap == null) {
				Toast.makeText(getApplicationContext(),
						"Sorry! unable to create maps", Toast.LENGTH_SHORT)
						.show();
			} else {
				googleMap.setMyLocationEnabled(true);

			}
			googleMap.setOnMapClickListener(this);
		}
	}

	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		switch (requestCode) {
		case (ROUTE_ACTIVITY): {
			if (resultCode == Activity.RESULT_OK) {
				if (data != null) {
					Bundle b = data.getExtras();
					if (b != null) {
						String startPlace = b.getString("startplace");
						String endPlace = b.getString("endplace");
						System.out.println("startPlace : " + startPlace);
						System.out.println("endPlace : " + endPlace);

						HttpASync async = new HttpASync();
						String encodeStartPlace = "";
						String encodeEndPlace = "";
						try {
							encodeStartPlace = URLEncoder.encode(startPlace,
									"UTF-8");
							encodeEndPlace = URLEncoder.encode(endPlace,
									"UTF-8");

						} catch (UnsupportedEncodingException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
						String url = AppConstant.ROUTE_PATH + "?startplace="
								+ encodeStartPlace + "&endplace="
								+ encodeEndPlace;
						async.setOnRequestListener(this);
						async.execute(url);
						clickListener.onClick(scrollView);
						showProgress("Finding best Route...");

					}
				}
			}
			break;
		}
		}
	}

	@Override
	public void onResponseReceived(String response) {
		System.out
				.println("HomeScreenActivity.onResponseReceived()" + response);
		Gson gson = new Gson();

		routesOptions = gson.fromJson(response, new TypeToken<List<TRoute>>() {
		}.getType());
		System.out.println("Total routes = " + routesOptions.size());
		runOnUiThread(new Runnable() {
			private int color[] = { Color.BLUE, Color.RED, Color.GREEN,
					Color.CYAN, Color.MAGENTA, Color.YELLOW };

			@Override
			public void run() {
				hideProgress();

				for (Polyline lin : line) {
					lin.remove();
				}
				line = new ArrayList<Polyline>();
				firstRoute = 0;
				for (int i = 0; i < routesOptions.size(); i++) {
					TRoute route = routesOptions.get(i);
					drawRoute(route,color[i%6]);
					ArrayList<TDistance> steps =route.getSteps();
					double dis= 0;
					for(int  j=0;j<steps.size();j++) {
					TDistance tdis =steps.get(i);
					dis+=tdis.getDistance();
					
					}
					String info = "Total distance for route " + (i + 1)
							+ ": dis \n";
					info += "Tdrive time :" + route.getDesTdriveDuration()
							+ "\n";
					info += "Google time : " + route.getDesGDuration() + "\n";
					Toast.makeText(HomeScreenActivity.this, info,
							Toast.LENGTH_SHORT).show();
				}

				googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
						currentlocation, 14));

			}

			private void drawRoute(TRoute route, int color) {
				System.out.println("drawRoute()");

				PolylineOptions options = new PolylineOptions().width(5)
						.color(color).geodesic(true);
				ArrayList<TDistance> list = route.getSteps();
				System.out.println("List size : " + list.size());
				String polyLine = route.getOverviewPolyLine();
				// options.add(new LatLng(route.getSourceLat(),
				// route.getSourceLong()));
				List<LatLng> point = decodePoly(polyLine);
				for (int i = 0; i < point.size(); i++) {
					if (firstRoute == 0) {
						currentlocation = new LatLng(point.get(i).latitude,
								point.get(i).longitude);
						firstRoute++;
					}
					options.add(new LatLng(point.get(i).latitude,
							point.get(i).longitude));

				}
				// //////options.add(new
				// LatLng(route.getDesLat(),route.getDesLong()));
				// options.addAll(point);
				/*
				 * for (int i = 0; i < list.size(); i++) { TDistance distance =
				 * list.get(i); String polyLine = distance.getPolyLine();
				 * List<LatLng> point =
				 * decodePoly(polyLine);////////////////////
				 * ///////////////////// options.addAll(point);
				 * 
				 * 
				 * }
				 */

				Polyline line1 = googleMap.addPolyline(options);

				line.add(line1);

			}

		     private ArrayList<LatLng> decodePoly(String encoded) {
		         ArrayList<LatLng> poly = new ArrayList<LatLng>();
		         int index = 0, len = encoded.length();
		         int lat = 0, lng = 0;
		         while (index < len) {
		             int b, shift = 0, result = 0;
		             do {
		                 b = encoded.charAt(index++) - 63;
		                 result |= (b & 0x1f) << shift;
		                 shift += 5;
		             } while (b >= 0x20);
		             int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
		             lat += dlat;
		             shift = 0;
		             result = 0;
		             do {
		                 b = encoded.charAt(index++) - 63;
		                 result |= (b & 0x1f) << shift;
		                 shift += 5;
		             } while (b >= 0x20);
		             int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
		             lng += dlng;

		             LatLng position = new LatLng((double) lat / 1E5, (double) lng / 1E5);
		             poly.add(position);
		         }
		         return poly;
		     }
		});

	}

	@Override
	public void onMapClick(LatLng arg0) {
		if (routesOptions != null) {
			 String color[] = { "BLUE", "RED","GREEN","CYAN","MAGENTA","YELLOW" };
			for (int i = 0; i < routesOptions.size(); i++) {
				TRoute route = routesOptions.get(i);
				ArrayList<TDistance> steps = route.getSteps();
				double dis = 0;
				for (int j = 0; j < steps.size(); j++) {
					TDistance tdis = steps.get(i);
					dis += tdis.getDistance();

				}
				String info = "Total distance for route (in "+color[i%6]+") " + (i + 1)
						+ ": "+dis+" \n";
				System.out.println("distance is"+dis);
				long tDuration =route.getDesTdriveDuration();
				
				info += "Tdrive time :" +getTimeInString(tDuration) + "\n";
				info += "Google time : " + getTimeInString(route.getDesGDuration()) + "\n";
				
				
				Toast.makeText(HomeScreenActivity.this, info,
						Toast.LENGTH_SHORT).show();
			}
		}

	}
	private String getTimeInString(long milliseconds){
		return String.format("%d min, %d sec", 
			    TimeUnit.MILLISECONDS.toMinutes(milliseconds),
			    TimeUnit.MILLISECONDS.toSeconds(milliseconds) - 
			    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliseconds))
			);
	}
}
